home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmbase-grok-1.2 / editwin.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  12KB  |  397 lines

  1. /*
  2.  * Create and destroy a simple text editing popup. It is installed when
  3.  * a procedural database is to be edited.
  4.  * The string entered or removed by the user are stored back into the
  5.  * proper string pointers.
  6.  *
  7.  *    destroy_edit_popup()
  8.  *    create_edit_popup(title, initial, readonly, help)
  9.  *    edit_file(name, readonly, create, title, help)
  10.  */
  11.  
  12. #include "config.h"
  13. #include <X11/Xos.h>
  14. #include <stdlib.h>
  15. #include <sys/stat.h>
  16. #include <time.h>
  17. #include <Xm/Xm.h>
  18. #include <Xm/DialogS.h>
  19. #include <Xm/Form.h>
  20. #include <Xm/LabelP.h>
  21. #include <Xm/LabelG.h>
  22. #include <Xm/PushBP.h>
  23. #include <Xm/PushBG.h>
  24. #include <Xm/ScrolledW.h>
  25. #include <Xm/Text.h>
  26. #include <Xm/Protocols.h>
  27. #include "grok.h"
  28. #include "form.h"
  29. #include "proto.h"
  30.  
  31. static void done_callback   (Widget, int, XmToggleButtonCallbackStruct *);
  32. static void cancel_callback (Widget, int, XmToggleButtonCallbackStruct *);
  33. static void delete_callback (Widget, int, XmToggleButtonCallbackStruct *);
  34. static void clear_callback  (Widget, int, XmToggleButtonCallbackStruct *);
  35.  
  36. extern int        errno;
  37. extern XmFontList    fontlist[NFONTS];
  38. extern Pixel        color[NCOLS];    /* colors: COL_* */
  39. extern Display        *display;    /* everybody uses the same server */
  40. extern Widget        toplevel;    /* top-level shell for icon name */
  41. static BOOL        have_shell;    /* message popup exists if TRUE */
  42. static char        **source;    /* ptr to string ptr of default */
  43. static char        *sourcefile;    /* if nonzero, file to write back to */
  44. static Widget        shell;        /* popup menu shell */
  45. static Widget        text;        /* text widget */
  46. Widget            w_name;        /* filename text between buttons */
  47.  
  48.  
  49. /*
  50.  * destroy a popup. Remove it from the screen, and destroy its widgets.
  51.  * If <sourcefile> is nonzero, write the text to that file. Otherwise,
  52.  * if <source> is nonzero, store a pointer to the text there. Otherwise,
  53.  * discard the text. The first choice implements editing scripts for
  54.  * procedural databases.
  55.  */
  56.  
  57. void destroy_edit_popup(void)
  58. {
  59.     char        *string;    /* contents of text widget */
  60.     FILE        *fp;        /* file to write */
  61.     char        *name;        /* file name */
  62.  
  63.     if (!have_shell)
  64.         return;
  65.     if (sourcefile) {
  66.         if (!(fp = fopen(name = sourcefile, "w"))) {
  67.             int e = errno;
  68.             fp = fopen(name = "/tmp/grokback", "w");
  69.             create_error_popup(toplevel, e, fp
  70.                 ? "Failed to create file %s, wrote to %s"
  71.                 : "Failed to create file %s or backup file %s",
  72.                             sourcefile, name);
  73.             if (!fp)
  74.                 return;
  75.         }
  76.         string = XmTextGetString(text);
  77.         if (!string || !*string) {
  78.             fclose(fp);
  79.             unlink(name);
  80.  
  81.         } else if (fwrite(string, strlen(string), 1, fp) != 1) {
  82.             create_error_popup(toplevel, errno,
  83.                     "Failed to write to file %s", name);
  84.             fclose(fp);
  85.             XtFree(string);
  86.             return;
  87.         } else
  88.             fclose(fp);
  89.         XtFree(string);
  90.         if (chmod(name, 0700))
  91.             create_error_popup(toplevel, errno,
  92.              "Failed to chmod 700 %s\nThe file is not executable.",
  93.                                 name);
  94.         free(sourcefile);
  95.         sourcefile = 0;
  96.  
  97.     } else if (source) {
  98.         if (*source)
  99.             free(*source);
  100.         string = XmTextGetString(text);
  101.         *source = *string ? mystrdup(string) : 0;
  102.         XtFree(string);
  103.         source = 0;
  104.     }
  105.     XtPopdown(shell);
  106.     XtDestroyWidget(shell);
  107.     have_shell = FALSE;
  108. }
  109.  
  110.  
  111. /*
  112.  * create an editor popup as a separate application shell.
  113.  */
  114.  
  115. void create_edit_popup(
  116.     char            *title,        /* menu title string */
  117.     char            **initial,    /* initial default text */
  118.     BOOL            readonly,    /* not modifiable if TRUE */
  119.     char            *helptag)    /* help tag */
  120. {
  121.     Widget            form, but=0, w, help;
  122.     Arg            args[20];
  123.     int            n;
  124.     Atom            closewindow;
  125.  
  126.     destroy_edit_popup();
  127.  
  128.     n = 0;
  129.     XtSetArg(args[n], XmNdeleteResponse,    XmDO_NOTHING);        n++;
  130.     XtSetArg(args[n], XmNiconic,        False);            n++;
  131.     shell = XtAppCreateShell(title, "Grok",
  132.             applicationShellWidgetClass, display, args, n);
  133.     set_icon(shell, 1);
  134.     form = XtCreateManagedWidget("editform", xmFormWidgetClass,
  135.             shell, NULL, 0);
  136.     XtAddCallback(form, XmNhelpCallback,
  137.             (XtCallbackProc)help_callback, (XtPointer)helptag);
  138.  
  139.                             /*-- buttons --*/
  140.     if (!readonly) {
  141.       n = 0;
  142.       XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM);        n++;
  143.       XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  144.       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  145.       XtSetArg(args[n], XmNleftOffset,    8);            n++;
  146.       XtSetArg(args[n], XmNwidth,        80);            n++;
  147.       XtSetArg(args[n], XmNtraversalOn,    False);            n++;
  148.       but = XtCreateManagedWidget("Delete", xmPushButtonWidgetClass,
  149.             form, args, n);
  150.       XtAddCallback(but, XmNactivateCallback,
  151.               (XtCallbackProc)delete_callback, (XtPointer)0);
  152.       XtAddCallback(but, XmNhelpCallback,
  153.               (XtCallbackProc)help_callback,(XtPointer)"msg_delete");
  154.  
  155.       n = 0;
  156.       XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM);        n++;
  157.       XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  158.       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  159.       XtSetArg(args[n], XmNleftWidget,    but);            n++;
  160.       XtSetArg(args[n], XmNleftOffset,    8);            n++;
  161.       XtSetArg(args[n], XmNwidth,        80);            n++;
  162.       XtSetArg(args[n], XmNtraversalOn,    False);            n++;
  163.       but = XtCreateManagedWidget("Clear", xmPushButtonWidgetClass,
  164.             form, args, n);
  165.       XtAddCallback(but, XmNactivateCallback,
  166.               (XtCallbackProc)clear_callback, (XtPointer)0);
  167.       XtAddCallback(but, XmNhelpCallback,
  168.               (XtCallbackProc)help_callback, (XtPointer)"msg_clear");
  169.     }
  170.     n = 0;
  171.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  172.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  173.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  174.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  175.     XtSetArg(args[n], XmNwidth,        80);            n++;
  176.     w = help = XtCreateManagedWidget("Help", xmPushButtonWidgetClass,
  177.             form, args, n);
  178.     XtAddCallback(help, XmNactivateCallback,
  179.             (XtCallbackProc)help_callback, (XtPointer)helptag);
  180.     if (!readonly) {
  181.       n = 0;
  182.       XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM);        n++;
  183.       XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  184.       XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  185.       XtSetArg(args[n], XmNrightWidget,    w);            n++;
  186.       XtSetArg(args[n], XmNrightOffset,    8);            n++;
  187.       XtSetArg(args[n], XmNwidth,        80);            n++;
  188.       w = XtCreateManagedWidget("Cancel", xmPushButtonWidgetClass,
  189.               form, args, n);
  190.       XtAddCallback(w, XmNactivateCallback,
  191.               (XtCallbackProc)cancel_callback, (XtPointer)0);
  192.       XtAddCallback(w, XmNhelpCallback,
  193.               (XtCallbackProc)help_callback,(XtPointer)"msg_cancel");
  194.     }
  195.     n = 0;
  196.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  197.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  198.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  199.     XtSetArg(args[n], XmNrightWidget,    w);            n++;
  200.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  201.     XtSetArg(args[n], XmNwidth,        80);            n++;
  202.     w = XtCreateManagedWidget(readonly ? "Done" : "Save",
  203.             xmPushButtonWidgetClass, form, args, n);
  204.     XtAddCallback(w, XmNactivateCallback,
  205.             (XtCallbackProc)done_callback, (XtPointer)0);
  206.     XtAddCallback(w, XmNhelpCallback,
  207.             (XtCallbackProc)help_callback, (XtPointer)"msg_done");
  208.  
  209.                             /*-- filename --*/
  210.     n = 0;
  211.     if (but) {
  212.       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  213.       XtSetArg(args[n], XmNleftWidget,    but);            n++;
  214.     } else {
  215.       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  216.     }
  217.     XtSetArg(args[n], XmNleftOffset,    8);            n++;
  218.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  219.     XtSetArg(args[n], XmNrightWidget,    w);            n++;
  220.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  221.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  222.     XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  223.     w_name = XtCreateManagedWidget(" ", xmLabelWidgetClass,
  224.             form, args, n);
  225.                             /*-- text --*/
  226.     n = 0;
  227.     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  228.     XtSetArg(args[n], XmNtopOffset,        8);            n++;
  229.     XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_WIDGET);    n++;
  230.     XtSetArg(args[n], XmNbottomWidget,    help);            n++;
  231.     XtSetArg(args[n], XmNbottomOffset,    16);            n++;
  232.     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  233.     XtSetArg(args[n], XmNleftOffset,    8);            n++;
  234.     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  235.     XtSetArg(args[n], XmNrightOffset,    8);            n++;
  236.     XtSetArg(args[n], XmNhighlightThickness,0);            n++;
  237.     XtSetArg(args[n], XmNeditMode,        XmMULTI_LINE_EDIT);    n++;
  238.     XtSetArg(args[n], XmNcolumns,        80);            n++;
  239.     XtSetArg(args[n], XmNrows,        24);            n++;
  240.     XtSetArg(args[n], XmNscrollVertical,    True);            n++;
  241.     XtSetArg(args[n], XmNpendingDelete,    False);            n++;
  242.     XtSetArg(args[n], XmNeditable,        !readonly);        n++;
  243.     XtSetArg(args[n], XmNfontList,        fontlist[FONT_COURIER]);n++;
  244.     text = XmCreateScrolledText(form, "text", args, n);
  245.     if (initial && *initial) {
  246.         XmTextSetString(text, *initial);
  247.         XmTextSetInsertionPosition(text, strlen(*initial));
  248.     }
  249.     XtVaSetValues(text, XmNbackground, color[COL_SHEET], NULL);
  250.     XtManageChild(text);
  251.  
  252.     XtPopup(shell, XtGrabNone);
  253.     closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
  254.     XmAddWMProtocolCallback(shell, closewindow,
  255.             (XtCallbackProc)done_callback, (XtPointer)shell);
  256.     have_shell = TRUE;
  257.     source = readonly ? 0 : initial;
  258. }
  259.  
  260.  
  261. /*-------------------------------------------------- callbacks --------------*/
  262. /*
  263.  * All of these routines are direct X callbacks.
  264.  */
  265.  
  266. /*ARGSUSED*/
  267. static void done_callback(
  268.     Widget                widget,
  269.     int                item,
  270.     XmToggleButtonCallbackStruct    *data)
  271. {
  272.     destroy_edit_popup();
  273. }
  274.  
  275.  
  276. static void discard(void)
  277. {
  278.     if (sourcefile)
  279.         free(sourcefile);
  280.     else if (source && *source)
  281.         free(*source);
  282.     sourcefile = 0;
  283.     source = 0;
  284.     destroy_edit_popup();
  285. }
  286.  
  287. /*ARGSUSED*/
  288. static void cancel_callback(
  289.     Widget                widget,
  290.     int                item,
  291.     XmToggleButtonCallbackStruct    *data)
  292. {
  293.     create_query_popup(widget, discard, "msg_discard",
  294.         "Press OK to confirm discarding\nall changes to the text");
  295. }
  296.  
  297.  
  298. /*ARGSUSED*/
  299. static void delete_callback(
  300.     Widget                widget,
  301.     int                item,
  302.     XmToggleButtonCallbackStruct    *data)
  303. {
  304.     XmTextSetString(text, "");
  305.     destroy_edit_popup();
  306. }
  307.  
  308.  
  309. /*ARGSUSED*/
  310. static void clear_callback(
  311.     Widget                widget,
  312.     int                item,
  313.     XmToggleButtonCallbackStruct    *data)
  314. {
  315.     XmTextSetString(text, "");
  316.     XmTextSetInsertionPosition(text, 0);
  317. }
  318.  
  319.  
  320. /*-------------------------------------------------- file I/O ---------------*/
  321. /*
  322.  * read file and put it into a text window. This is used for print-to-window.
  323.  * The help argument determines what will come up when Help in the editor
  324.  * window is pressed; it must be one of the %% tags in grok.hlp.
  325.  */
  326.  
  327. void edit_file(
  328.     char        *name,        /* file name to read */
  329.     BOOL        readonly,    /* not modifiable if TRUE */
  330.     BOOL        create,        /* create if nonexistent if TRUE */
  331.     char        *title,        /* if nonzero, window title */
  332.     char        *helptag)    /* help tag */
  333. {
  334.     FILE        *fp;        /* file to read */
  335.     long        size;        /* file size */
  336.     char        *text;        /* text read from file */
  337.     BOOL        writable;    /* have write permission for file? */
  338.  
  339.     name = resolve_tilde(name, 0);
  340.     if (!title)
  341.         title = name;
  342.     if (access(name, F_OK)) {
  343.         if (!create || readonly) {
  344.             create_error_popup(toplevel, errno,
  345.                         "Cannot open %s", name);
  346.             return;
  347.         }
  348.         writable = TRUE;
  349.         create_edit_popup(title, 0, readonly, helptag);
  350.         print_button(w_name, "File %s (new file)",
  351.             (text = strrchr(name, '/')) ? text+1 : name);
  352.     } else {
  353.         create = FALSE;
  354.         if (access(name, R_OK)) {
  355.             create_error_popup(toplevel, errno,
  356.                         "Cannot read %s", name);
  357.             return;
  358.         }
  359.         writable = !access(name, W_OK);
  360.  
  361.         if (!(fp = fopen(name, "r"))) {
  362.             create_error_popup(toplevel, errno,
  363.                         "Cannot read %s", name);
  364.             return;
  365.         }
  366.         fseek(fp, 0, 2);
  367.         size = ftell(fp);
  368.         rewind(fp);
  369.         if (size) {
  370.             if (!(text = malloc(size+1))) {
  371.                 create_error_popup(toplevel, errno,
  372.                         "Cannot alloc %d bytes for %s",
  373.                         size+1, name);
  374.                 fclose(fp);
  375.                 return;
  376.             }
  377.             if (fread(text, size, 1, fp) != 1) {
  378.                 create_error_popup(toplevel, errno,
  379.                         "Cannot read %s", name);
  380.                 fclose(fp);
  381.                 return;
  382.             }
  383.             text[size] = 0;
  384.         }
  385.         fclose(fp);
  386.         create_edit_popup(title, text ? &text : 0,
  387.                 readonly || !writable, helptag);
  388.         free(text);
  389.         if (!readonly)
  390.             print_button(w_name, "File %s %s",
  391.                 (text = strrchr(name, '/')) ? text+1 : name,
  392.                 writable ? "" : "(read only)");
  393.     }
  394.     if (!readonly && writable)
  395.         sourcefile = mystrdup(name);
  396. }
  397.